package com.lintf.bot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lintf.bot.domain.*;
import com.lintf.bot.domain.constant.Constant;
import com.lintf.bot.domain.dto.BotGroupInviteAddDTO;
import com.lintf.bot.domain.dto.BotGroupInviteListDTO;
import com.lintf.bot.domain.dto.BotGroupInviteUpdateDTO;
import com.lintf.bot.domain.enums.NoticeTypeEnums;
import com.lintf.bot.domain.enums.ReviewStatusEnums;
import com.lintf.bot.domain.enums.StatusEnums;
import com.lintf.bot.domain.enums.SysFileTypeEnums;
import com.lintf.bot.domain.vo.BotGroupInviteListVo;
import com.lintf.bot.mapper.BotGroupInviteMapper;
import com.lintf.bot.notice.NoticeUtils;
import com.lintf.bot.service.*;
import com.lintf.common.core.domain.entity.SysUser;
import com.lintf.common.utils.SecurityUtils;
import com.lintf.system.domain.SysFileInfo;
import com.lintf.system.service.ISysFileInfoService;
import com.lintf.system.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lintf
 * @description 针对表【bot_group_invite】的数据库操作Service实现
 * @createDate 2024-03-13 12:57:24
 */
@Service
public class BotGroupInviteServiceImpl extends ServiceImpl<BotGroupInviteMapper, BotGroupInvite>
        implements IBotGroupInviteService {

    @Autowired
    private IBotGroupService botGroupService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IBotDailyService botDailyService;
    @Autowired
    private IBotEatingService botEatingService;
    @Autowired
    private IBotMoneyService botMoneyService;
    @Autowired
    private IBotBillService botBillService;
    @Autowired
    private IBotMoneyUserService botMoneyUserService;
    @Autowired
    private IBotBillCellUserService botBillCellUserService;
    @Autowired
    private IBotBillCellService botBillCellService;
    @Autowired
    private ISysFileInfoService sysFileInfoService;
    @Autowired
    private NoticeUtils noticeUtils;

    @Override
    public List<BotGroupInviteListVo> list(BotGroupInviteListDTO dto) {
        LambdaQueryWrapper<BotGroupInvite> wrapper = new LambdaQueryWrapper<>();
        if (!dto.isOwnApply()) {
            LambdaQueryWrapper<BotGroup> groupWrapper = new LambdaQueryWrapper<>();
            groupWrapper.select(BotGroup::getId).eq(BotGroup::getCreateBy, SecurityUtils.getUserId());
            List<Integer> groupIds = botGroupService.list(groupWrapper).stream().map(BotGroup::getId).collect(Collectors.toList());
            wrapper.in(BotGroupInvite::getGroupId, groupIds);
        } else {
            wrapper.eq(BotGroupInvite::getInviteUserId, SecurityUtils.getUserId());
        }
        List<BotGroupInviteListVo> list = new ArrayList<>();
        BotGroupInviteListVo vo;
        List<BotGroupInvite> inviteList = baseMapper.selectList(wrapper);
        Set<Integer> refIds = null;
        Set<Long> userIds = null;
        if (!dto.isOwnApply()) {
            userIds = inviteList.stream().map(BotGroupInvite::getInviteUserId).collect(Collectors.toSet());
            SysUser sysUser = new SysUser();
            sysUser.setUserIds(new ArrayList<>(userIds));
            List<SysUser> sysUsers = sysUserService.selectUserListOfNoPage(sysUser);
            for (BotGroupInvite groupInvite : inviteList) {
                vo = new BotGroupInviteListVo();
                BeanUtils.copyProperties(groupInvite, vo);
                vo.setGroup(botGroupService.getById(groupInvite.getGroupId()));
                SysUser user = sysUsers.stream().filter(item -> Objects.equals(item.getUserId(), groupInvite.getInviteUserId())).findFirst().get();
                vo.setUser(user);
                list.add(vo);
            }
        } else {
            refIds = inviteList.stream().map(BotGroupInvite::getGroupId).collect(Collectors.toSet());
            LambdaQueryWrapper<SysFileInfo> fileWrapper = new LambdaQueryWrapper<>();
            fileWrapper.in(SysFileInfo::getRefId, refIds)
                    .eq(SysFileInfo::getRefType, SysFileTypeEnums.GROUP.getValue());
            List<SysFileInfo> sysFileInfos = sysFileInfoService.list(fileWrapper);
            for (BotGroupInvite groupInvite : inviteList) {
                vo = new BotGroupInviteListVo();
                BeanUtils.copyProperties(groupInvite, vo);
                vo.setGroup(botGroupService.getById(groupInvite.getGroupId()));
                SysFileInfo sysFileInfo = sysFileInfos.stream().filter(item -> Objects.equals(item.getRefId(), groupInvite.getGroupId())).findFirst().get();
                vo.setSysFileInfo(sysFileInfo);
                list.add(vo);
            }
        }
        return list;
    }

    @Override
    public int getOneOfReview(BotGroupInviteListDTO dto) {
        LambdaQueryWrapper<BotGroupInvite> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BotGroupInvite::getGroupId, dto.getGroupId())
                .eq(BotGroupInvite::getStatus, StatusEnums.COMPLETED.getValue())
                .eq(BotGroupInvite::getInviteUserId, SecurityUtils.getUserId());
        return Math.toIntExact(baseMapper.selectCount(wrapper));
    }

    @Override
    public List<SysUser> getOneOfUser(BotGroupInviteListDTO dto) {
        Set<Long> userIds = null;
        if (dto.getGroupId() != 0) {
            LambdaQueryWrapper<BotGroupInvite> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(BotGroupInvite::getInviteUserId)
                    .eq(BotGroupInvite::getGroupId, dto.getGroupId())
                    .eq(BotGroupInvite::getStatus, StatusEnums.COMPLETED.getValue())
                    .eq(BotGroupInvite::getReview, ReviewStatusEnums.OK.getValue());
            userIds = baseMapper.selectList(wrapper).stream().map(BotGroupInvite::getInviteUserId).collect(Collectors.toSet());
            if (StringUtils.isEmpty(dto.getCreateBy())) {
                LambdaQueryWrapper<BotGroup> groupWrapper = new LambdaQueryWrapper<>();
                groupWrapper.select(BotGroup::getCreateBy)
                        .eq(BotGroup::getId, dto.getGroupId());
                BotGroup group = botGroupService.getOne(groupWrapper);
                userIds.add(Long.valueOf(group.getCreateBy()));
            } else {
                userIds.add(Long.valueOf(dto.getCreateBy()));
            }
        }
        SysUser sysUser = new SysUser();
        if (userIds != null) {
            sysUser.setUserIds(new ArrayList<>(userIds));
        }
        return sysUserService.selectUserListOfNoPage(sysUser);
    }

    @Override
    public List<SysUser> getGroupOfUser(BotGroupInviteListDTO dto) {
        Set<Long> userIds;
        SysUser sysUser = new SysUser();
        Long userId;
        if (dto.getExcludeOfUserId() != null) {
            userId = dto.getExcludeOfUserId();
        } else {
            userId = SecurityUtils.getUserId();
        }
        if (dto.getGroupId() != 0) {
            LambdaQueryWrapper<BotGroupInvite> wrapper = new LambdaQueryWrapper<>();
            wrapper.select(BotGroupInvite::getInviteUserId)
                    .eq(BotGroupInvite::getGroupId, dto.getGroupId())
                    .eq(BotGroupInvite::getStatus, StatusEnums.COMPLETED.getValue())
                    .eq(BotGroupInvite::getReview, ReviewStatusEnums.OK.getValue());
            List<BotGroupInvite> invites = baseMapper.selectList(wrapper);
            userIds = invites.stream().map(BotGroupInvite::getInviteUserId).collect(Collectors.toSet());
            userIds.add(Long.valueOf(botGroupService.getById(dto.getGroupId()).getCreateBy()));
            if (!dto.isIncludeOfOwn()) {
                userIds.remove(userId);
            }
            if (userIds.isEmpty()) {
                return new ArrayList<>();
            }
            sysUser.setUserIds(new ArrayList<>(userIds));
            return sysUserService.selectUserListOfNoPage(sysUser);
        } else {
            sysUser.setRemoveUserId(userId);
            return sysUserService.selectUserListOfNoPage(sysUser);
        }

    }

    @Override
    @Transactional
    public void add(BotGroupInviteAddDTO dto) {
        BotGroupInvite botGroupInvite = new BotGroupInvite();
        BeanUtils.copyProperties(dto, botGroupInvite);
        botGroupInvite.setInviteUserId(SecurityUtils.getUserId());
//                .setCreateParams();
        baseMapper.insert(botGroupInvite);
        BotGroup group = botGroupService.getById(dto.getGroupId());
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(SecurityUtils.getLoginUser().getUser().getNickName())
                .append("申请加入")
                .append(group.getGroupName());
        String title = stringBuilder.toString();
        noticeUtils.personPush(dto.getGroupId(), title, NoticeTypeEnums.CIRCLE_APPLICATION, title, Long.parseLong(group.getCreateBy()), dto.getGroupId());
    }

    @Override
    public void update(BotGroupInviteUpdateDTO dto) {
        BotGroupInvite botGroupInvite = new BotGroupInvite();
        BeanUtils.copyProperties(dto, botGroupInvite);
//        botGroupInvite.setUpdateParams();
        baseMapper.updateById(botGroupInvite);
        BotGroup group = botGroupService.getById(dto.getGroupId());
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(SecurityUtils.getLoginUser().getUser().getNickName());
        if (dto.getReview() == 1) {
            stringBuilder.append("同意了你的").append(Constant.CIRCLE_APPLICATION);
        } else {
            stringBuilder.append("拒绝了你的").append(Constant.CIRCLE_APPLICATION);
        }
        stringBuilder.append("(").append(group.getGroupName()).append(")");
        String title = stringBuilder.toString();
        noticeUtils.personPush(dto.getGroupId(), title, NoticeTypeEnums.CIRCLE_APPLICATION, title, dto.getInviteUserId(), dto.getGroupId());
    }

    @Override
    @Transactional
    public void remove(BotGroupInviteUpdateDTO dto) {
        LambdaQueryWrapper<BotGroupInvite> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(BotGroupInvite::getId)
                .eq(BotGroupInvite::getGroupId, dto.getGroupId())
                .eq(BotGroupInvite::getInviteUserId, dto.getInviteUserId());
        baseMapper.deleteById(baseMapper.selectOne(wrapper).getId());
        BotGroup group = botGroupService.getById(dto.getGroupId());
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(SecurityUtils.getLoginUser().getUser().getNickName())
                .append("将你移出")
                .append(group.getGroupName());
        String title = stringBuilder.toString();
        noticeUtils.personPush(dto.getGroupId(), title, NoticeTypeEnums.CIRCLE_APPLICATION, title, dto.getInviteUserId(), dto.getGroupId());
        if (!dto.isClear()) {
            return;
        }
        // 移除发布日常数据
        LambdaQueryWrapper<BotDaily> dailyWrapper = new LambdaQueryWrapper<>();
        dailyWrapper.eq(BotDaily::getCreateBy, dto.getInviteUserId())
                .eq(BotDaily::getGroupId, dto.getGroupId());
        botDailyService.remove(dailyWrapper);
        // 移除发布干饭数据
        LambdaQueryWrapper<BotEating> eatingWrapper = new LambdaQueryWrapper<>();
        eatingWrapper.eq(BotEating::getCreateBy, dto.getInviteUserId())
                .eq(BotEating::getGroupId, dto.getGroupId());
        botEatingService.remove(eatingWrapper);
        // 移除发布钱袋数据
        LambdaQueryWrapper<BotMoney> moneyWrapper = new LambdaQueryWrapper<>();
        moneyWrapper.eq(BotMoney::getCreateBy, dto.getInviteUserId())
                .eq(BotMoney::getGroupId, dto.getGroupId());
        botMoneyService.remove(moneyWrapper);
        // 移除发布清单数据
        LambdaQueryWrapper<BotBill> billWrapper = new LambdaQueryWrapper<>();
        billWrapper.eq(BotBill::getCreateBy, dto.getInviteUserId())
                .eq(BotBill::getGroupId, dto.getGroupId());
        botBillService.remove(billWrapper);
        LambdaQueryWrapper<BotBillCell> billCellWrapper = new LambdaQueryWrapper<>();
        billCellWrapper.eq(BotBillCell::getBotBillId, dto.getId());
        botBillCellService.remove(billCellWrapper);
        // 移除钱袋共享数据
        moneyWrapper = new LambdaQueryWrapper<>();
        moneyWrapper.select(BotMoney::getId)
                .eq(BotMoney::getGroupId, dto.getGroupId());
        List<Integer> moneyIds = botMoneyService.list(moneyWrapper).stream().map(BotMoney::getId).collect(Collectors.toList());
        LambdaQueryWrapper<BotMoneyUser> moneyUserWrapper = new LambdaQueryWrapper<>();
        moneyUserWrapper.in(BotMoneyUser::getBotMoneyId, moneyIds)
                .eq(BotMoneyUser::getUserId, dto.getInviteUserId());
        botMoneyUserService.remove(moneyUserWrapper);
        // 移除待办指定执行人
        billWrapper = new LambdaQueryWrapper<>();
        billWrapper.select(BotBill::getId)
                .eq(BotBill::getGroupId, dto.getGroupId());
        List<Integer> billIds = botBillService.list(billWrapper).stream().map(BotBill::getId).collect(Collectors.toList());
        billCellWrapper = new LambdaQueryWrapper<>();
        billCellWrapper.select(BotBillCell::getId)
                .in(BotBillCell::getBotBillId, billIds);
        List<Integer> billCellIds = botBillCellService.list(billCellWrapper).stream().map(BotBillCell::getId).collect(Collectors.toList());
        LambdaQueryWrapper<BotBillCellUser> billCellUserWrapper = new LambdaQueryWrapper<>();
        billCellUserWrapper.in(BotBillCellUser::getBotBillCellId, billCellIds);
        Map<Integer, List<BotBillCellUser>> collect = botBillCellUserService.list(billCellUserWrapper).stream().collect(Collectors.groupingBy(BotBillCellUser::getBotBillCellId));
        for (Map.Entry<Integer, List<BotBillCellUser>> entry : collect.entrySet()) {
            boolean result = entry.getValue().stream().anyMatch(item -> Objects.equals(item.getUserId(), dto.getInviteUserId()));
            if (result) {
                if (entry.getValue().size() > 1) {
                    billCellUserWrapper = new LambdaQueryWrapper<>();
                    billCellUserWrapper.eq(BotBillCellUser::getBotBillCellId, entry.getKey())
                            .eq(BotBillCellUser::getUserId, dto.getInviteUserId());
                    botBillCellUserService.remove(billCellUserWrapper);
                } else {
                    botBillCellService.removeById(entry.getKey());
                }
            }
        }
    }

}




